package com.xiaoyu.lanling.feature.register.fragment

import `in`.srain.cube.util.TimeUtils
import `in`.srain.cube.util.UTUtil
import android.os.Bundle
import android.text.Editable
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.app.GlobalUI
import com.xiaoyu.base.event.AppEventBus
import com.xiaoyu.base.event.SimpleEventHandler
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.event.register.CheckInviteCodeEvent
import com.xiaoyu.lanling.event.register.RandomNameEvent
import com.xiaoyu.lanling.event.register.RegisterFirstNextButtonClickEvent
import com.xiaoyu.lanling.feature.register.data.RegisterData
import com.xiaoyu.lanling.view.AlertHoloDateDialog
import com.xiaoyu.lanling.view.OnShowFragment
import com.xiaoyu.lanling.view.listener.BaseTextWatcher
import kotlinx.android.synthetic.main.register_first_fragment.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*

class RegisterFirstFragment : OnShowFragment() {

    companion object {
        private val TAG = RegisterFirstFragment::class.java.simpleName

        fun create(fragmentManager: FragmentManager): OnShowFragment {
            val fragment = (fragmentManager.findFragmentByTag(TAG) as? OnShowFragment)
                    ?: RegisterFirstFragment()
            return fragment
        }
    }

    private inner class NameTextWatcher : BaseTextWatcher() {
        override fun afterTextChanged(s: Editable?) {
            updateNextButton()
        }
    }

    private val requestTag = Any()

    private var timePicker: AlertHoloDateDialog? = null
    private val nameTextWatcher = NameTextWatcher()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.register_first_fragment, container, false)
    }

    override fun onViewCreatedSafelyAfterAppFinishInit(view: View, savedInstanceState: Bundle?) {
        super.onViewCreatedSafelyAfterAppFinishInit(view, savedInstanceState)
        initBind()
        initEvent()
        initData()
    }

    override fun onStartSafelyAfterAppFinishInit(isFirstTimeStart: Boolean) {
        super.onStartSafelyAfterAppFinishInit(isFirstTimeStart)
        name_edit_text?.addTextChangedListener(nameTextWatcher)
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        if (isVisibleToUser) {
            logEventForEnter()
        }
    }

    private fun logEventForEnter() {
        UTUtil.getInstance().logEvent("enter_register_basic_page")
        UTUtil.getInstance().flushLogEvent()
    }

    override fun onStop() {
        super.onStop()
        name_edit_text?.removeTextChangedListener(nameTextWatcher)
    }

    private fun initBind() {
        back?.setOnClickDebounceListener { activity?.finish() }
        sex_male?.setOnClickDebounceListener { updateSex(User.SEX_MAN) }
        sex_female?.setOnClickDebounceListener { updateSex(User.SEX_WOMAN) }
        name_random_button?.setOnClickDebounceListener { RegisterData.randomName(requestTag, if (sex_female.isSelected) User.SEX_WOMAN else User.SEX_MAN) }
        birthday_edit?.setOnClickDebounceListener { showTimePicker() }
        next?.setOnClickDebounceListener {
            val inviteCode = invite_code_edit_text.text.toString().trim()
            RegisterData.checkInviteCode(requestTag, inviteCode)
        }
    }

    private fun updateSex(sex: String) {
        when (sex) {
            User.SEX_MAN -> {
                sex_male?.isSelected = true
                sex_female?.isSelected = false
            }
            User.SEX_WOMAN -> {
                sex_male?.isSelected = false
                sex_female?.isSelected = true
            }
        }
        GlobalUI.getInstance().showToast(getString(R.string.register_sex_can_not_change_toast))
        updateNextButton()
    }

    private fun initEvent() {
        AppEventBus.bindContainerAndHandler(this, object : SimpleEventHandler() {
            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: RandomNameEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                name_edit_text?.setText(event.name)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: CheckInviteCodeEvent) {
                if (event.valid) {
                    val sex = if (sex_female.isSelected) User.SEX_WOMAN else User.SEX_MAN
                    val inviteCode = invite_code_edit_text.text.toString().trim()
                    RegisterFirstNextButtonClickEvent(name_edit_text?.text.toString(), sex, birthday_edit_text?.text.toString(), inviteCode).post()
                } else {
                    GlobalUI.getInstance().showToast(AppContext.getString(R.string.register_invalid_invite_code))
                }
            }
        })
    }

    private fun initData() {
        val name = activity?.intent?.getStringExtra(Constant.IntentKey.KEY_NAME) ?: ""
        if (TextUtils.isEmpty(name)) {
            RegisterData.randomName(requestTag)
        } else {
            name_edit_text.setText(name)
        }
    }

    private fun showTimePicker() {
        if (timePicker == null) {
            val calendar = Calendar.getInstance();
            val curYear = calendar.get(Calendar.YEAR);
            val curMonth = calendar.get(Calendar.MONTH);
            val curDay = calendar.get(Calendar.DAY_OF_MONTH);

            val yearSelected = curYear - 23;
            val monthSelected = 0;
            val daySelected = 1;

            val yearMax = curYear - 18;
            val monthMax = 0;
            val dayMax = if (!isLeapYear(yearMax) && curMonth == Calendar.FEBRUARY && curDay == 29) curDay - 1 else curDay;

            val yearMin = curYear - 90;
            val monthMin = 0;
            val dayMin = 1;

            timePicker = AlertHoloDateDialog.create(activity)
                    .setTitle(AppContext.getString(R.string.register_birthday_dialog_title))
                    .setSelectedDate(yearSelected, monthSelected, daySelected)
                    .setMaxDate(yearMax, monthMax, dayMax)
                    .setMinDate(yearMin, monthMin, dayMin)
                    .setOnDateResultListener { year, month, dayOfMonth ->
                        calendar.set(year, month, dayOfMonth)
                        val dateString = TimeUtils.getDate(calendar.time)
                        this.birthday_edit_text?.setText(dateString)
                        updateNextButton()
                    }
                    .show()
        }
        timePicker?.show()
    }

    private fun isLeapYear(yearMax: Int): Boolean {
        return (GregorianCalendar.getInstance() as GregorianCalendar).isLeapYear(yearMax)
    }

    private fun updateNextButton() {
        val isSexSelected = sex_male?.isSelected == true || sex_female?.isSelected == true
        val enable = name_edit_text?.text?.isNotEmpty() == true && isSexSelected && birthday_edit_text?.text?.isNotEmpty() == true
        next?.isEnabled = enable
    }
}